package com.feather.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import com.feather.annotation.*;


public class ActionController {
	
	private Map<String, ActionUnit> actionUnitMap = new HashMap<String, ActionUnit>();
	
	private List<ActionFinder> actionFinderList = new ArrayList<ActionFinder>();
	
	public ActionController()
	{
	}
	
	public void addObjectMethod(Object object)
	{
		try {
			Class<?> clazz = object.getClass();
			for(Method method : clazz.getDeclaredMethods())
			{
				Annotation methodAnnotation = method.getAnnotation(ActionMethod.class);
				if(methodAnnotation == null)
					continue;
				
				addActionUnit(method.getName(), new ActionUnitMethod(object, method));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void addActionFinder(ActionFinder actionFinder)
	{
		actionFinderList.add(actionFinder);
	}
	
	public void addActionUnit(String name, ActionUnit actionUnit)
	{
		actionUnitMap.put(name, actionUnit);
	}
	
	public Object doURI(String uri, Object params) throws Exception
	{
		Object action = null;
		for(ActionFinder e : actionFinderList)
		{
			action = e.find(uri);
			if(action != null) break;
		}
		
		if(action == null)
			return "action is null";
		
		return doAction(action, params);
	}
	
	@SuppressWarnings("unchecked")
	public Object doAction(Object action, Object params) throws Exception
	{
		if(action instanceof Map)
		{
			Map<String, Object> mapAction = (Map<String, Object>) action;
			String actionName = (String) mapAction.get("_action");
			if(actionName != null)
			{
				ActionUnit actionUnit = actionUnitMap.get(actionName);
				if(actionUnit != null)
				{
					Map<String, Object> inputActionMap = (Map<String, Object>) mapAction.get("_input");
					Map<String, Object> inputMap = new HashMap<String, Object>();
					for(Map.Entry<String, Object> e : inputActionMap.entrySet())
					{
						inputMap.put(e.getKey(), doAction(e.getValue(), params));
					}
					
					return actionUnit.execute(inputMap);
				}
				throw new Exception(actionName + " not found!");
			}
			else
			{
				Map<String, Object> resultMap = new HashMap<String, Object>();
				for(Map.Entry<String, Object> e : mapAction.entrySet())
				{
					resultMap.put(e.getKey(), doAction(e.getValue(), params));
				}
				return resultMap;
			}
		}
		else if(action instanceof String)
		{
			String strAction = (String) action;
			if("$params".equals(strAction))
				return params;
			return action;
		}
		else
		{
			return action;
		}
		
		
	}
}
